/*
 * Copyright (C) 2021 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package uk.co.alt236.btlescan.slice;

import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.aafwk.content.Operation;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.RoundProgressBar;
import ohos.agp.components.Text;
import ohos.agp.utils.LayoutAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.agp.window.service.DisplayAttributes;
import ohos.agp.window.service.DisplayManager;
import ohos.app.Context;
import ohos.bluetooth.BluetoothHost;
import ohos.bluetooth.ble.BleCentralManager;
import ohos.bluetooth.ble.BleCentralManagerCallback;
import ohos.bluetooth.ble.BleScanFilter;
import ohos.bluetooth.ble.BleScanResult;
import ohos.utils.IntentConstants;
import ohos.utils.net.Uri;
import uk.co.alt236.bluetoothlelib.device.BluetoothLeDevice;
import uk.co.alt236.btlescan.ResourceTable;
import uk.co.alt236.btlescan.adapter.DeviceItemProvider;

import java.util.ArrayList;
import java.util.List;

/**
 * DeviceAbilitySlice
 *
 * @author ljx
 * @since 2021-04-29
 */
public class MainAbilitySlice extends AbilitySlice {
    private static final int WIDTH = 340;
    private static final int RADIUS = 15;
    private BluetoothHost bluetoothHost;
    private ScanCallback centralManagerCallback;
    private BleCentralManager centralManager;
    private ListContainer listContainer;
    private RoundProgressBar mProgressBar;
    private int rotate = 0;
    private boolean isRotation = true;
    private Button scan;
    private DeviceItemProvider sampleItemProvider;
    private List<BluetoothLeDevice> listDevice;
    private Text itemNum;
    private Text tvState;
    private final int increaseRotate = 20;
    private final int maxRotate = 360;
    private final int delayTime = 100;

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
        super.setUIContent(ResourceTable.Layout_ability_main);

        // 获取蓝牙本机管理对象
        bluetoothHost = BluetoothHost.getDefaultHost(this);
        bluetoothHost.enableBt();
        centralManagerCallback = new ScanCallback();
        centralManager = new BleCentralManager(this, centralManagerCallback);
        mProgressBar = (RoundProgressBar) findComponentById(ResourceTable.Id_round_progress_bar);
        scan = (Button) findComponentById(ResourceTable.Id_scan);
        listContainer = (ListContainer) findComponentById(ResourceTable.Id_listcontainer);
        tvState = (Text) findComponentById(ResourceTable.Id_ble_state);
        itemNum = (Text) findComponentById(ResourceTable.Id_item_num);
        Text about = (Text) findComponentById(ResourceTable.Id_tv_about);
        about.setClickedListener(v -> {
            about();
        });
        init();
    }

    public void init() {
        scan.setClickedListener(v -> {
            int state = bluetoothHost.getBtState();
            if (state == BluetoothHost.STATE_ON) {
                tvState.setText("on");
                if ("scan".equals(scan.getText())) {
                    scan.setText("stop");
                    startRotate();
                    List<BleScanFilter> filters = new ArrayList<>();
                    centralManager.startScan(filters);
                } else {
                    scan.setText("scan");
                    stopRotate();
                    centralManager.stopScan();
                }
            } else {
                bluetoothHost.enableBt();
            }
        });
        if (bluetoothHost.getBtState() == BluetoothHost.STATE_ON) {
            tvState.setText("on");
        } else {
            tvState.setText("off");
        }

        listDevice = new ArrayList<>();
        sampleItemProvider = new DeviceItemProvider(listDevice, this);
        listContainer.setItemProvider(sampleItemProvider);
        listContainer.setItemClickedListener((container, component, position, id) -> {
            BluetoothLeDevice deviceItem = (BluetoothLeDevice) listContainer.getItemProvider().getItem(position);

            Intent intent = new Intent();
            intent.setParam("device", deviceItem);
            present(new DeviceAbilitySlice(), intent);
        });
    }

    private void about() {
        DirectionalLayout directionalLayout = (DirectionalLayout) LayoutScatter.getInstance(this)
                .parse(ResourceTable.Layout_dialog_picker, null, false);
        CommonDialog dialog = new CommonDialog(this);
        dialog.setContentCustomComponent(directionalLayout);
        dialog.setAutoClosable(true);
        dialog.setSize(vp2px(this, WIDTH), DirectionalLayout.LayoutConfig.MATCH_CONTENT);
        dialog.setAlignment(LayoutAlignment.CENTER);
        dialog.setCornerRadius(vp2px(this, RADIUS));
        dialog.show();
        Text confirm = (Text) directionalLayout.findComponentById(ResourceTable.Id_tv_confirm);
        confirm.setClickedListener(v -> {
            dialog.destroy();
        });
        Text tvUrl = (Text) directionalLayout.findComponentById(ResourceTable.Id_tv_url);
        tvUrl.setText("Github: https://github.com/alt236/Bluetooth-LE-Library---And" + "roid");
        tvUrl.setClickedListener(v -> {
            initWeb();
            dialog.destroy();
        });
    }

    private void initWeb() {
        Intent intents = new Intent();
        Operation operation = new Intent.OperationBuilder()
                .withUri(Uri.parse("https://github.com/alt236/Bluetooth-LE-Library---And" + "roid"))
                .withAction(IntentConstants.ACTION_SEARCH)
                .build();
        intents.setOperation(operation);
        startAbility(intents);
    }

    private int vp2px(Context context, float vp) {
        DisplayAttributes attributes = DisplayManager.getInstance().getDefaultDisplay(context).get().getAttributes();
        return (int) (attributes.densityPixels * vp);
    }

    private void startRotate() {
        isRotation = true;
        mProgressBar.setVisibility(Component.VISIBLE);
        getUITaskDispatcher().delayDispatch(() -> {
            rotate = rotate + increaseRotate;
            if (rotate == maxRotate) {
                rotate = 0;
            }
            if (isRotation && mProgressBar != null && mProgressBar.getVisibility() == Component.VISIBLE) {
                mProgressBar.setRotation(rotate);
                startRotate();
            }
        }, delayTime);
    }

    private void stopRotate() {
        isRotation = false;
        mProgressBar.setVisibility(Component.INVISIBLE);
    }

    /**
     * ScanCallback
     *
     * @author ljx
     * @since 2021-04-29
     */
    public class ScanCallback implements BleCentralManagerCallback {
        List<BleScanResult> results = new ArrayList<>();

        @Override
        public void scanResultEvent(BleScanResult resultCode) {
            // 对扫描结果进行处理
            results.add(resultCode);
            int rssi = resultCode.getRssi();
            byte[] scanRecord = resultCode.getRawData();
            BluetoothLeDevice deviceLe = new BluetoothLeDevice(resultCode,
                    rssi, scanRecord, System.currentTimeMillis());
            getUITaskDispatcher().asyncDispatch(() -> {
                for (int index = 0; index < listDevice.size(); index++) {
                    if (deviceLe.getAddress().equals(listDevice.get(index).getAddress())) {
                        BluetoothLeDevice item = listDevice.get(index);
                        item.updateRssiReading(System.currentTimeMillis(), rssi);
                        return;
                    }
                }
                listDevice.add(deviceLe);
                sampleItemProvider.setData(listDevice);
                itemNum.setText("Items：" + listDevice.size());
            });
        }

        @Override
        public void scanFailedEvent(int resultCode) {
        }

        @Override
        public void groupScanResultsEvent(List<BleScanResult> list) {
        }
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }
}